package org.gamma.gwt;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;

public class GammaWidget extends Widget {
    private final String className;
    private final String jarName;
    private final String codeBase;
    private final int width;
    private final int height;
    protected final String elementName;
    
    public GammaWidget(String strClassName, String strElementName) {
        this(strClassName, strElementName, null, null, 0, 0);
    }
    
    public GammaWidget(String strClassName, String strElementName, String strJARName) {
        this(strClassName, strElementName, strJARName, null, 0, 0);
    }
    
    public GammaWidget(String strClassName, String strElementName, String strJARName, String strCodeBase, int nWidth, int nHeight) {
        if(nHeight > 0) {
            height = nHeight;
        }
        else {
            height = 1;
        }
        if(nWidth > 0) {
            width = nWidth;
        }
        else {
            width = 1;
        }
        if( (strCodeBase != null) && ( !strCodeBase.equals("") ) ) {
            codeBase = strCodeBase;
        }
        else {
            codeBase = "./";
        }
        jarName = strJARName;
        elementName = strElementName;
        className = strClassName;
        render();
    }

    @Override
    public String toString() {
        return className;
    }
    
    private void render() {
        Element div  = DOM.createDiv();

        String strHtml = "<applet name='";
        strHtml += elementName;
        strHtml += "' code='";
        strHtml += className;
        strHtml += "' codebase='";
        strHtml += codeBase; 
        if( (jarName != null) && ( !jarName.equals("") ) ) {
            strHtml += "' archive='";
            strHtml += jarName;    
        }
        strHtml += "' width='";
        strHtml += width;
        strHtml += "' height='";
        strHtml += height;
        strHtml += "'";
        strHtml += " MAYSCRIPT";
        strHtml += ">";
        if( (jarName != null) && ( !jarName.equals("") ) ) {
            strHtml += "<param name='cache_archive' value='";
            strHtml += jarName;
            strHtml += "'>";
        }
        strHtml += "Java Plug-In not installed.</applet>";

        DOM.setInnerHTML(div, strHtml);
        setElement(div);
    }

    public String getElementName() {
        return elementName;
    }
    
    public void publish(JavaScriptObject input, AsyncCallback<JavaScriptObject> callback) {
        //Arbitrating the callback before queueing the message avoids a 
        //race condition where one of the applet's threads fires a 
        //response before we're ready for it.
        int idx = ResponseBroker.getInstance().subscribe(callback);
        if(isReady()) {
            _publish(input, idx);
        }
    }
    
    /**
     * Note: If the initial condition fails, this indicates that the Applet 
     *          either failed to load or hasn't finished loading yet.
     */
    
    private native void _publish(JavaScriptObject input, int idx) /*-{
        var applet = $doc[this.@org.gamma.gwt.GammaWidget::getElementName()()];
        applet.publish(input, idx);
    }-*/;

    public native boolean isReady() /*-{
        var applet = $doc[this.@org.gamma.gwt.GammaWidget::getElementName()()];
        var ready = false;
        var done = false;
        if(applet) {
            try {
                ready = applet.isActive();
                done = true;
            } catch(err) {
            }
            if(!done) {
                try {
                    ready = applet.isActive;
                    done = true;
                } catch(err) {
                }
            }
        }
        return (done && ready);
    }-*/;
    
}
